//===========================================================================================================================
// Cuberry - http://www.cuberry.net
// Copyright (c) 2012
// by Peacequare® - Amir Moussa
//===========================================================================================================================
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 
// as published by the Free Software Foundation, either version 3 of the License, or any later version.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// This program is distributed in the hope that it will be useful.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//===========================================================================================================================

using System;
using System.ComponentModel;
using System.Linq;
using System.Transactions;
using P2.Cuberry.Framework.BOLBase;
using P2.Cuberry.Framework.Helper;
using P2.Cuberry.Framework.Helper.Configuration;
using P2.Cuberry.Framework.Security;
using P2.Cuberry.Modules.Clinicom.CCPatient.DAL;


namespace P2.Cuberry.Modules.Clinicom.CCPatient.BusinessEntities
{
    public class CCPatient : BizObject, INotifyPropertyChanged
    {

        #region Members

        //++KeyID
        int _patientID = -1;
        public int PatientID
        {
            get { return _patientID; }
            protected set
            {
                if (_patientID != value)
                {
                    _patientID = value;
                }
            }
        }

        //Add++
        string _firstNameEn = String.Empty;
        public string FirstNameEn
        {
            get { return _firstNameEn; }
            set
            {
                if (value != _firstNameEn)
                {
                    _firstNameEn = value;
                    Modified = true;
                }
            }
        }

        string _middleNameEn = String.Empty;
        public string MiddleNameEn
        {
            get { return _middleNameEn; }
            set
            {
                if (value != _middleNameEn)
                {
                    _middleNameEn = value;
                    Modified = true;
                }
            }
        }

        string _lastNameEn = String.Empty;
        public string LastNameEn
        {
            get { return _lastNameEn; }
            set
            {
                if (value != _lastNameEn)
                {
                    _lastNameEn = value;
                    Modified = true;
                }
            }
        }

        string _firstNameAr = String.Empty;
        public string FirstNameAr
        {
            get { return _firstNameAr; }
            set
            {
                if (value != _firstNameAr)
                {
                    _firstNameAr = value;
                    Modified = true;
                }
            }
        }

        string _middleNameAr = String.Empty;
        public string MiddleNameAr
        {
            get { return _middleNameAr; }
            set
            {
                if (value != _middleNameAr)
                {
                    _middleNameAr = value;
                    Modified = true;
                }
            }
        }

        string _lastNameAr = String.Empty;
        public string LastNameAr
        {
            get { return _lastNameAr; }
            set
            {
                if (value != _lastNameAr)
                {
                    _lastNameAr = value;
                    Modified = true;
                }
            }
        }

        string _street = String.Empty;
        public string Street
        {
            get { return _street; }
            set
            {
                if (value != _street)
                {
                    _street = value;
                    Modified = true;
                }
            }
        }

        string _zIPCode = String.Empty;
        public string ZIPCode
        {
            get { return _zIPCode; }
            set
            {
                if (value != _zIPCode)
                {
                    _zIPCode = value;
                    Modified = true;
                }
            }
        }

        string _city = String.Empty;
        public string City
        {
            get { return _city; }
            set
            {
                if (value != _city)
                {
                    _city = value;
                    Modified = true;
                }
            }
        }

        string _eMail = String.Empty;
        public string EMail
        {
            get { return _eMail; }
            set
            {
                if (value != _eMail)
                {
                    _eMail = value;
                    Modified = true;
                }
            }
        }

        string _phoneMobile = String.Empty;
        public string PhoneMobile
        {
            get { return _phoneMobile; }
            set
            {
                if (value != _phoneMobile)
                {
                    _phoneMobile = value;
                    Modified = true;
                }
            }
        }

        string _phoneOther = String.Empty;
        public string PhoneOther
        {
            get { return _phoneOther; }
            set
            {
                if (value != _phoneOther)
                {
                    _phoneOther = value;
                    Modified = true;
                }
            }
        }

        string _phoneOtherDescription = String.Empty;
        public string PhoneOtherDescription
        {
            get { return _phoneOtherDescription; }
            set
            {
                if (value != _phoneOtherDescription)
                {
                    _phoneOtherDescription = value;
                    Modified = true;
                }
            }
        }

        DateTime? _dateOfBirth = DateTime.Now;
        public DateTime? DateOfBirth
        {
            get { return _dateOfBirth; }
            set
            {
                if (value != _dateOfBirth)
                {
                    _dateOfBirth = value;
                    Modified = true;
                }
            }
        }

        int? _maritalStatusID = null;
        public int? MaritalStatusID
        {
            get { return _maritalStatusID; }
            set
            {
                if (value != _maritalStatusID)
                {
                    _maritalStatusID = value;
                    Modified = true;
                }
            }
        }

        int? _nationalityID = null;
        public int? NationalityID
        {
            get { return _nationalityID; }
            set
            {
                if (value != _nationalityID)
                {
                    _nationalityID = value;
                    Modified = true;
                }
            }
        }

        string _personalIDNo = String.Empty;
        public string PersonalIDNo
        {
            get { return _personalIDNo; }
            set
            {
                if (value != _personalIDNo)
                {
                    _personalIDNo = value;
                    Modified = true;
                }
            }
        }

        int? _personalIDTypeID = null;
        public int? PersonalIDTypeID
        {
            get { return _personalIDTypeID; }
            set
            {
                if (value != _personalIDTypeID)
                {
                    _personalIDTypeID = value;
                    Modified = true;
                }
            }
        }

        int? _iDOwnerID = null;
        public int? IDOwnerID
        {
            get { return _iDOwnerID; }
            set
            {
                if (value != _iDOwnerID)
                {
                    _iDOwnerID = value;
                    Modified = true;
                }
            }
        }

        int? _genderID = null;
        public int? GenderID
        {
            get { return _genderID; }
            set
            {
                if (value != _genderID)
                {
                    _genderID = value;
                    Modified = true;
                }
            }
        }

        int? _religionID = null;
        public int? ReligionID
        {
            get { return _religionID; }
            set
            {
                if (value != _religionID)
                {
                    _religionID = value;
                    Modified = true;
                }
            }
        }

        string _bloodGroup = String.Empty;
        public string BloodGroup
        {
            get { return _bloodGroup; }
            set
            {
                if (value != _bloodGroup)
                {
                    _bloodGroup = value;
                    Modified = true;
                }
            }
        }

        int? _contractorInsuranceID = null;
        public int? ContractorInsuranceID
        {
            get { return _contractorInsuranceID; }
            set
            {
                if (value != _contractorInsuranceID)
                {
                    _contractorInsuranceID = value;
                    Modified = true;
                }
            }
        }

        string _note = String.Empty;
        public string Note
        {
            get { return _note; }
            set
            {
                if (value != _note)
                {
                    _note = value;
                    Modified = true;
                }
            }
        }




        //DDL++
        int? _countryID = null;
        public int? CountryID
        {
            get { return _countryID; }
            set
            {
                if (value != _countryID)
                    _countryID = value;
                Modified = true;
            }
        }

        public XConfigCountry XConfigCountry
        {
            get
            { return BusinessEntities.XConfigCountry.GetItem(this.CountryID.GetValueOrDefault(-1)); }
        }



        #endregion


        #region Computed Properties
        //DDL++
        public string XConfigCountryCur
        {
            get
            {
                if (this.XConfigCountry != null)
                    return this.XConfigCountry.XConfigCountryCur;
                else
                    return "";
            }
        }



        #endregion


        #region Constructors

        public CCPatient()
        {
            Modified = false;
        }


        public CCPatient(int keyPatientID)
        {
            this._patientID = keyPatientID;
            FillMyObject();
            Modified = false;
        }


        public CCPatient(DAL.CCPatient ccPatient)
        {
            Load(ccPatient);
        }

        #endregion


        #region Read Operations

        //load an existing Instance
        public void Load(int keyPatientID)
        {
            PatientID = keyPatientID;
            if (keyPatientID >= 0)
            {
                FillMyObject();
            }
            else
            {
                Load(null);
            }
            Modified = false;
        }


        //Add++ //DDL++
        public void Load(DAL.CCPatient sourceEntity)
        {
            if (sourceEntity != null)
            {
                this.PatientID = sourceEntity.PatientID;

                this.FirstNameEn = sourceEntity.FirstNameEn;
                this.MiddleNameEn = sourceEntity.MiddleNameEn;
                this.LastNameEn = sourceEntity.LastNameEn;
                this.FirstNameAr = sourceEntity.FirstNameAr;
                this.MiddleNameAr = sourceEntity.MiddleNameAr;
                this.LastNameAr = sourceEntity.LastNameAr;
                this.Street = sourceEntity.Street;
                this.ZIPCode = sourceEntity.ZIPCode;
                this.City = sourceEntity.City;
                this.EMail = sourceEntity.EMail;
                this.PhoneMobile = sourceEntity.PhoneMobile;
                this.PhoneOther = sourceEntity.PhoneOther;
                this.PhoneOtherDescription = sourceEntity.PhoneOtherDescription;
                this.DateOfBirth = sourceEntity.DateOfBirth;
                this.MaritalStatusID = sourceEntity.MaritalStatusID;
                this.NationalityID = sourceEntity.NationalityID;
                this.PersonalIDNo = sourceEntity.PersonalIDNo;
                this.PersonalIDTypeID = sourceEntity.PersonalIDTypeID;
                this.IDOwnerID = sourceEntity.IDOwnerID;
                this.GenderID = sourceEntity.GenderID;
                this.ReligionID = sourceEntity.ReligionID;
                this.BloodGroup = sourceEntity.BloodGroup;
                this.ContractorInsuranceID = sourceEntity.ContractorInsuranceID;
                this.Note = sourceEntity.Note;

                this.CountryID = sourceEntity.CountryID;

                //Default Fields                
                this.CreatedBy = sourceEntity.CreatedBy;
                this.CreatedOn = sourceEntity.CreatedOn;
                this.EditedBy = sourceEntity.EditedBy;
                this.EditedOn = sourceEntity.EditedOn;
                this.Timestamp = sourceEntity.TStamp;
                this.StatusID = sourceEntity.StatusID.GetValueOrDefault(P2.Cuberry.Framework.Helper.Workflows.WorkflowStatus.GetInitialStatus(this.EntityName).StatusID);
            }
            else
            {
                this.PatientID = -1;

                this.FirstNameEn = String.Empty;
                this.MiddleNameEn = String.Empty;
                this.LastNameEn = String.Empty;
                this.FirstNameAr = String.Empty;
                this.MiddleNameAr = String.Empty;
                this.LastNameAr = String.Empty;
                this.Street = String.Empty;
                this.ZIPCode = String.Empty;
                this.City = String.Empty;
                this.EMail = String.Empty;
                this.PhoneMobile = String.Empty;
                this.PhoneOther = String.Empty;
                this.PhoneOtherDescription = String.Empty;
                this.DateOfBirth = null;
                this.MaritalStatusID = null;
                this.NationalityID = null;
                this.PersonalIDNo = String.Empty;
                this.PersonalIDTypeID = null;
                this.IDOwnerID = null;
                this.GenderID = null;
                this.ReligionID = null;
                this.BloodGroup = String.Empty;
                this.ContractorInsuranceID = null;
                this.Note = String.Empty;

                this.CountryID = null;

                //Default Fields
                this.CreatedBy = String.Empty;
                this.EditedBy = String.Empty;
                P2.Cuberry.Framework.Helper.Workflows.WorkflowStatus initStatus = P2.Cuberry.Framework.Helper.Workflows.WorkflowStatus.GetInitialStatus(this.EntityName);
                this.StatusID = initStatus.StatusID;
            }
            Modified = false;
        }


        internal P2TransactionMessage FillMyObject()
        {
            P2TransactionMessage tMsg = new P2TransactionMessage();
            if (this._patientID < 0)
            {
                Load(this._patientID);
                return tMsg;
            }

            try
            {
                string connectionString = ConfigurationSetUp.GetEntConnectionString("Business", Properties.Settings.Default.EntityResources);
                using (CCPatientDataContext db = new CCPatientDataContext(connectionString))
                {
                    var xElements = from xElement in db.CCPatient
                                    where xElement.PatientID == this._patientID
                                    select xElement;

                    foreach (var xElementx in xElements)
                    {
                        Load(xElementx);
                    }
                }

                tMsg.TransactionStatus = "green";
                tMsg.MessageText = "TMsg_FillMyObjectSuceeded";
            }
            catch (Exception ex)
            {
                tMsg.TransactionStatus = "red";
                tMsg.MessageText = "Error_Error";
                tMsg.MessageFreeText = ex.Message;
                P2ExceptionHandler.LogException(ex, this);
            }

            this.MessageStack.Add(tMsg);
            return tMsg;

        }
        #endregion


        #region Update Operations

        //Add++
        public P2MessageStack InsertAndUpdate(P2MessageStack MessageStack, bool checkDoublicate)
        {
            MessageStack.AddRange(this.Validator.Validate(this));

            try
            {
                if (MessageStack.StatusMessage.MessageStatus == P2ValidationStatus.green || MessageStack.StatusMessage.MessageStatus == P2ValidationStatus.white || (MessageStack.StatusMessage.MessageStatus == P2ValidationStatus.yellow && P2Validator.YellowErrorDialog.AskSave(MessageStack)))
                {
                    MessageStack.Clear();
                    string connectionString = ConfigurationSetUp.GetEntConnectionString("Business", Properties.Settings.Default.EntityResources);

                    using (DAL.CCPatientDataContext db = new DAL.CCPatientDataContext(connectionString))
                    {
                        using (TransactionScope ts = new TransactionScope())
                        {
                            //Add++ //DDL++ //--> Set it to starting status.
                            if (this.StatusID == -1) this.StatusID = 7001;

                            if (string.IsNullOrEmpty(this.CreatedBy)) this.CreatedBy = User.Current.UserID;
                            this.EditedBy = User.Current.UserID;

                            DAL.CCPatient editedItem;
                            if (this.PatientID < 0)
                            {
                                editedItem = new DAL.CCPatient()
                                {
                                    FirstNameEn = this.FirstNameEn,
                                    MiddleNameEn = this.MiddleNameEn,
                                    LastNameEn = this.LastNameEn,
                                    FirstNameAr = this.FirstNameAr,
                                    MiddleNameAr = this.MiddleNameAr,
                                    LastNameAr = this.LastNameAr,
                                    Street = this.Street,
                                    ZIPCode = this.ZIPCode,
                                    City = this.City,
                                    EMail = this.EMail,
                                    PhoneMobile = this.PhoneMobile,
                                    PhoneOther = this.PhoneOther,
                                    PhoneOtherDescription = this.PhoneOtherDescription,
                                    DateOfBirth = this.DateOfBirth,
                                    MaritalStatusID = this.MaritalStatusID,
                                    NationalityID = this.NationalityID,
                                    PersonalIDNo = this.PersonalIDNo,
                                    PersonalIDTypeID = this.PersonalIDTypeID,
                                    IDOwnerID = this.IDOwnerID,
                                    GenderID = this.GenderID,
                                    ReligionID = this.ReligionID,
                                    BloodGroup = this.BloodGroup,
                                    ContractorInsuranceID = this.ContractorInsuranceID,
                                    Note = this.Note,

                                    CountryID = this.CountryID,

                                    //Default Fields
                                    CreatedBy = User.Current.UserID,
                                    CreatedOn = DateTime.Now,
                                    EditedBy = User.Current.UserID,
                                    EditedOn = DateTime.Now,
                                    StatusID = this.StatusID
                                };
                                db.AddToCCPatient(editedItem);
                            }
                            else
                            {
                                editedItem = (from xItem in db.CCPatient
                                              where xItem.PatientID == this.PatientID
                                              select xItem).First();
                                if (editedItem.TStamp == this.Timestamp)
                                {
                                    //Add++ //DDL++
                                    editedItem.FirstNameEn = this.FirstNameEn;
                                    editedItem.MiddleNameEn = this.MiddleNameEn;
                                    editedItem.LastNameEn = this.LastNameEn;
                                    editedItem.FirstNameAr = this.FirstNameAr;
                                    editedItem.MiddleNameAr = this.MiddleNameAr;
                                    editedItem.LastNameAr = this.LastNameAr;
                                    editedItem.Street = this.Street;
                                    editedItem.ZIPCode = this.ZIPCode;
                                    editedItem.City = this.City;
                                    editedItem.EMail = this.EMail;
                                    editedItem.PhoneMobile = this.PhoneMobile;
                                    editedItem.PhoneOther = this.PhoneOther;
                                    editedItem.PhoneOtherDescription = this.PhoneOtherDescription;
                                    editedItem.DateOfBirth = this.DateOfBirth;
                                    editedItem.MaritalStatusID = this.MaritalStatusID;
                                    editedItem.NationalityID = this.NationalityID;
                                    editedItem.PersonalIDNo = this.PersonalIDNo;
                                    editedItem.PersonalIDTypeID = this.PersonalIDTypeID;
                                    editedItem.IDOwnerID = this.IDOwnerID;
                                    editedItem.GenderID = this.GenderID;
                                    editedItem.ReligionID = this.ReligionID;
                                    editedItem.BloodGroup = this.BloodGroup;
                                    editedItem.ContractorInsuranceID = this.ContractorInsuranceID;
                                    editedItem.Note = this.Note;
                                    
                                    editedItem.CountryID = this.CountryID;

                                    //Default Fields
                                    editedItem.EditedBy = User.Current.UserID;
                                    editedItem.EditedOn = DateTime.Now;
                                    editedItem.StatusID = this.StatusID;

                                    //track changes!
                                    this.SaveChangeLog(this.PatientID);
                                }
                                else
                                {
                                    MessageStack.Add(new P2TransactionMessage("red", P2Translator.GetResource("TMsg_AccountNotUpdated"))); //--> rename it
                                }
                            }
                            if (MessageStack.StatusMessage.MessageStatus != P2ValidationStatus.red)
                            {
                                db.SaveChanges();
                                ts.Complete();
                                if (this.PatientID < 0)
                                {
                                    MessageStack.Add(new P2TransactionMessage("green", P2Translator.GetResource("TMsg_PatientAdded")));
                                    this.PatientID = editedItem.PatientID;
                                }
                                else
                                    MessageStack.Add(new P2TransactionMessage("green", P2Translator.GetResource("TMsg_PatientUpdated")));
                            }
                        }
                    }

                    FillMyObject();
                    Modified = false;
                }
            }
            catch (Exception ex)
            {
                MessageStack.Add(new P2TransactionMessage("red", P2Translator.GetResource("Error_Error")));
                P2ExceptionHandler.LogException(ex, this);
            }
            return MessageStack;
        }

        #endregion


        #region Property Changed

        public event PropertyChangedEventHandler PropertyChanged;


        private void OnPropertyChanged(string propertyName)
        {
            Modified = true;
            PropertyChangedEventHandler Handler = PropertyChanged;
            if (Handler != null) Handler(this, new PropertyChangedEventArgs(propertyName));
        }

        //Add++ //DDL++
        public void OnAllPropertiesChanged()
        {
            OnPropertyChanged("PatientID");

            OnPropertyChanged("FirstNameEn");
            OnPropertyChanged("MiddleNameEn");
            OnPropertyChanged("LastNameEn");
            OnPropertyChanged("FirstNameAr");
            OnPropertyChanged("MiddleNameAr");
            OnPropertyChanged("LastNameAr");
            OnPropertyChanged("Street");
            OnPropertyChanged("ZIPCode");
            OnPropertyChanged("City");
            OnPropertyChanged("EMail");
            OnPropertyChanged("PhoneMobile");
            OnPropertyChanged("PhoneOther");
            OnPropertyChanged("PhoneOtherDescription");
            OnPropertyChanged("DateOfBirth");
            OnPropertyChanged("MaritalStatusID");
            OnPropertyChanged("NationalityID");
            OnPropertyChanged("PersonalIDNo");
            OnPropertyChanged("PersonalIDTypeID");
            OnPropertyChanged("IDOwnerID");
            OnPropertyChanged("GenderID");
            OnPropertyChanged("ReligionID");
            OnPropertyChanged("BloodGroup");
            OnPropertyChanged("ContractorInsuranceID");
            OnPropertyChanged("Note");


            OnPropertyChanged("CountryID");


            //Standard Fields
            OnPropertyChanged("StatusName");
            OnPropertyChanged("StatusID");
        }

        #endregion


        #region Validator

        public override P2Validator Validator
        {
            get
            {
                if (_validator == null)
                    _validator = new P2Validator(Properties.Settings.Default.ModuleName, this.EntityName, "PatientID", this);
                return _validator;
            }
        }

        #endregion
        
    }
}

